package com.dji.sample.wayline.service.impl;

import com.dji.sample.component.oss.model.OssConfiguration;
import com.dji.sample.component.oss.service.impl.OssServiceContext;
import com.dji.sample.wayline.service.IOssFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

/**
 * OSS文件服务实现类
 * 基于MinIO实现文件下载功能
 * 
 * @author ryan
 * @version 1.0
 * @date 2024/10/17
 */
@Service
@Slf4j
public class OssFileServiceImpl implements IOssFileService {

    @Autowired
    private OssServiceContext ossServiceContext;

    @Override
    public MultipartFile downloadFileByObjectKey(String objectKey) {
        return downloadFileByObjectKey(OssConfiguration.bucket, objectKey);
    }

    @Override
    public MultipartFile downloadFileByObjectKey(String bucket, String objectKey) {
        if (!StringUtils.hasText(objectKey)) {
            throw new IllegalArgumentException("ObjectKey不能为空");
        }
        
        if (!StringUtils.hasText(bucket)) {
            throw new IllegalArgumentException("Bucket不能为空");
        }

        try {
            log.info("开始从OSS下载文件，bucket: {}, objectKey: {}", bucket, objectKey);
            
            // 从OSS获取文件流
            InputStream inputStream = ossServiceContext.getObject(bucket, objectKey);
            if (inputStream == null) {
                throw new RuntimeException("文件不存在或下载失败，objectKey: " + objectKey);
            }

            // 将InputStream转换为byte数组
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            byte[] data = new byte[1024];
            int nRead;
            while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
                buffer.write(data, 0, nRead);
            }
            buffer.flush();
            byte[] fileBytes = buffer.toByteArray();

            // 从objectKey中提取文件名
            String fileName = extractFileNameFromObjectKey(objectKey);
            
            // 创建自定义MultipartFile实现
            MultipartFile multipartFile = new ByteArrayMultipartFile(
                    "file", 
                    fileName, 
                    getContentType(fileName), 
                    fileBytes
            );

            log.info("文件下载成功，文件名: {}, 文件大小: {} bytes", fileName, fileBytes.length);
            return multipartFile;

        } catch (IOException e) {
            log.error("下载文件失败，objectKey: {}, 错误信息: {}", objectKey, e.getMessage(), e);
            throw new RuntimeException("下载文件失败: " + e.getMessage(), e);
        } catch (Exception e) {
            log.error("下载文件时发生未知错误，objectKey: {}, 错误信息: {}", objectKey, e.getMessage(), e);
            throw new RuntimeException("下载文件时发生未知错误: " + e.getMessage(), e);
        }
    }

    @Override
    public String getFileUrlByObjectKey(String objectKey) {
        return getFileUrlByObjectKey(OssConfiguration.bucket, objectKey);
    }

    @Override
    public String getFileUrlByObjectKey(String bucket, String objectKey) {
        if (!StringUtils.hasText(objectKey)) {
            throw new IllegalArgumentException("ObjectKey不能为空");
        }
        
        if (!StringUtils.hasText(bucket)) {
            throw new IllegalArgumentException("Bucket不能为空");
        }

        try {
            log.info("开始获取文件URL，bucket: {}, objectKey: {}", bucket, objectKey);
            
            // 从OSS获取文件URL
            URL url = ossServiceContext.getObjectUrl(bucket, objectKey);
            if (url == null) {
                throw new RuntimeException("获取文件URL失败，objectKey: " + objectKey);
            }

            String urlString = url.toString();
            log.info("获取文件URL成功，objectKey: {}, URL: {}", objectKey, urlString);
            return urlString;

        } catch (Exception e) {
            log.error("获取文件URL时发生错误，objectKey: {}, 错误信息: {}", objectKey, e.getMessage(), e);
            throw new RuntimeException("获取文件URL失败: " + e.getMessage(), e);
        }
    }

    /**
     * 从ObjectKey中提取文件名
     * 
     * @param objectKey OSS对象键
     * @return 文件名
     */
    private String extractFileNameFromObjectKey(String objectKey) {
        if (!StringUtils.hasText(objectKey)) {
            return "unknown_file";
        }
        
        // 如果objectKey包含路径分隔符，取最后一部分作为文件名
        if (objectKey.contains("/")) {
            return objectKey.substring(objectKey.lastIndexOf("/") + 1);
        }
        
        return objectKey;
    }

    /**
     * 根据文件名获取ContentType
     * 
     * @param fileName 文件名
     * @return ContentType
     */
    private String getContentType(String fileName) {
        if (!StringUtils.hasText(fileName)) {
            return "application/octet-stream";
        }
        
        String lowerFileName = fileName.toLowerCase();
        if (lowerFileName.endsWith(".kmz")) {
            return "application/vnd.google-earth.kmz";
        } else if (lowerFileName.endsWith(".kml")) {
            return "application/vnd.google-earth.kml+xml";
        } else if (lowerFileName.endsWith(".zip")) {
            return "application/zip";
        } else if (lowerFileName.endsWith(".xml")) {
            return "application/xml";
        } else {
            return "application/octet-stream";
        }
    }

    /**
     * 自定义MultipartFile实现类
     */
    private static class ByteArrayMultipartFile implements MultipartFile {
        private final String name;
        private final String originalFilename;
        private final String contentType;
        private final byte[] content;

        public ByteArrayMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
            this.name = name;
            this.originalFilename = originalFilename;
            this.contentType = contentType;
            this.content = content;
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public String getOriginalFilename() {
            return originalFilename;
        }

        @Override
        public String getContentType() {
            return contentType;
        }

        @Override
        public boolean isEmpty() {
            return content == null || content.length == 0;
        }

        @Override
        public long getSize() {
            return content == null ? 0 : content.length;
        }

        @Override
        public byte[] getBytes() throws IOException {
            return content;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return new ByteArrayInputStream(content);
        }

        @Override
        public void transferTo(File dest) throws IOException, IllegalStateException {
            throw new UnsupportedOperationException("transferTo not supported");
        }
    }
}